header {
	package analisis;
	import jcram.*;
}

class Analex extends Lexer;

options {
	caseSensitiveLiterals = false;
	charVocabulary='\3'..'\377';
	testLiterals=false;
	k = 2;
}

tokens
{
    //Delimitadores
    FUNC_BEGIN_REP = "beginPlay"
    FUNC_END_REP = "endPlay"
    FUNC_BEGIN_DEF = "beginDEf"
    FUNC_END_DEF = "endDef"
 
	// Samples
    FUNC_LOAD_SAMPLE = "loadSample"
    FUNC_SAVE_SAMPLE = "saveSample"
    FUNC_REMOVE_SAMPLE = "removeSample"
    FUNC_GET_SAMPLE = "getSample"
    FUNC_GET_SPEED_SAMPLE_ = "getSpeedSample"
    FUNC_SET_SPEED_SAMPLE = "setSpeedSample"
    FUNC_CHANGE_SPEED_SAMPLE = "changeSpeedSample"
    FUNC_GET_VOL_SAMPLE = "getVolSample"
    FUNC_CHANGE_VOL_SAMPLE = "changeVolSample"
    FUNC_GET_LENGTH_SAMPLE = "getLengthSample"
    FUNC_REPEAT_SAMPLE = "repeatSample"
    FUNC_STEP_SAMPLE = "stepSample"
    FUNC_ATTENUATE_SAMPLE = "attenuateSample"

	// Sonidos (Pistas)
    FUNC_BEGIN_TRACK = "beginTrack"
    FUNC_END_TRACK = "endTrack"
    FUNC_ADD_TRACK = "addTrack"
    FUNC_LOAD_TRACK = "loadTrack"
    FUNC_SAVE_TRACK = "saveTrack"
    FUNC_DELETE_TRACK = "deleteTrack"
    FUNC_GET_NUMBER_TRACKS = "setNumberOfTrack"
    
    //Sonido Global
    FUNC_SET_GLOBAL_SPEED = "setGlobalSpeed"
    FUNC_GET_GLOBAL_SPEED = "getGlobalSpeed"
    FUNC_SET_GLOBAL_VOLUME = "setGlobalVolume"
    FUNC_GET_GLOBAL_VOLUME = "getGlobalVolume"
    FUNC_GET_LENGTH_TRACK = "getLengthTrank"
    FUNC_STEP_GLOBAL_SOUND = "stepGlobalSound"
    FUNC_ATTENUATE_GLOBAL_SOUND = "attenuateGlobalSound"
	
	// Sentencias de control
	RES_IF = "if";
	RES_PLAY_IF = "play_if";
	RES_ELSE = "else";
	RES_END_IF = "end_if";
	RES_WHILE = "while";
	RES_PLAY = "play";
	RES_END_WHILE = "end_while";
	RES_FOR = "for";
	RES_FROM = "from";
	RES_TO = "to";
	RES_INCREMENT = "increment";
	RES_END_FOR = "end_for";
	RES_WRT = "wrt";
	RES_READ_NUMBER = "read_number";
	RES_READ_STRING = "read_str";
	RES_PAUSA = "wait";
	RES_FINALIZAR = "@";
		
	// Literales booleanos
	LIT_VERDADERO = "true";
	LIT_FALSO = "false";
	
	// Tipos basicos
	TIPO_ENTERO = "int" ;
	TIPO_REAL = "float" ;
	TIPO_BOOLEANO = "bool" ;
	TIPO_CADENA = "string" ;
	
	// Literales
	LIT_REAL;
	LIT_ENTERO;
	
	// Variables
	VAR_ENTERO;
	VAR_REAL;
	VAR_CADENA;
	VAR_BOOLEANO;

	// Operaciones
	OP_MODULO = "MOD";
}

/*********************************************
 * Reglas de produccion del Analizador Lexico!
 *********************************************/
protected NL
	: (
	("\r\n") => "\r\n" //WINDOWS
	| '\r' //MACINTOSH
	| '\n' //UNIX
	) { newline(); }
;

/***********************************************
 * Ignorar espacios en blanco y saltos de linea
 ***********************************************/
BLANCO
	: ( ' '
	| '\t'
	| NL
	) { $setType(Token.SKIP); }
;

/*******************************************
 * Ignora los comentarios de una sola linea
 *******************************************/
COMENTARIO1:
	'#' (~('\n'|'\r'))* {$setType(Token.SKIP);}
;

/*******************************************
 * Ignora los comentarios de varias lineas
 *******************************************/
COMENTARIO2:
	'/*' ( NL | ~('\n' | '\r' | '}'))* '*/' {$setType(Token.SKIP);}
;

/*******************************************
 * Letras Espanolas
 *******************************************/
protected LETRA
: 'a'..'z'
| 'A'..'Z'
| 'ñ' | 'Ñ'
| 'á' | 'é' | 'í' | 'ó' | 'ú'
| 'Á' | 'É' | 'Í' | 'Ó' | 'Ú'
| 'ü' | 'Ü'
;

/*******************************************
 * Reconocimiento de los digitos mas usuales
 *******************************************/
protected DIGITO : '0'..'9';

/*******************************************
 * Regla que permite reconocer los literales
 *******************************************/
IDENT options {testLiterals=true;}
: (LETRA|'_') (LETRA|DIGITO|'_')* 
	{ 
		// Acción a realizar cuando se encuentra un identificador (determinar tipo)
		Object aux = TablaSimbolos.getVar(getText());
		if (aux != null)
		{
			if (aux.getClass() == Integer.class)
				$setType(VAR_ENTERO);
			else if (aux.getClass() == Float.class)
				$setType(VAR_REAL);
			else if (aux.getClass() == String.class)
				$setType(VAR_CADENA);
			else if (aux.getClass() == Boolean.class)
				$setType(VAR_BOOLEANO);
		}
		else
			$setType(IDENT);
	};

/********************************************
 * Reconocimiento de numeros enteros y reales
 ********************************************/
LIT_NUMERO : (( DIGITO )+ '.' ) =>
	( DIGITO )+ '.' ( DIGITO )*('f')? { $setType (LIT_REAL); }
	| ( DIGITO )+ { $setType (LIT_ENTERO); }
;

/*******************************************
 * Reconocimiento de simbolos separadores
 *******************************************/
PUNTO_COMA: ';';
COMA: ',';
PARENTESIS_AB: '(';
PARENTESIS_CE: ')';
DOS_PUNTOS: ':';

/*******************************************
 * Reconocimiento de operadores
 *******************************************/
OP_ASIGNACION : '=';
OP_IGUAL : "==" ;
OP_NO : '!';
OP_Y_LOGICO : "&&";
OP_O_LOGICO : "||";
OP_DISTINTO : "!=" ;
OP_MENOR : '<' ;
OP_MAYOR : '>' ;
OP_MAS : '+' ;
OP_MENOS : '-' ;
OP_PRODUCTO : '*' ;
OP_DIVISION : '/' ;
OP_EXPONENCIAL : '^' ;

/*******************************************
 * Reconocimiento de los literales de cadena
 *******************************************/
LIT_CADENA :
'"' !
( ~('"'|'\n'|'\r') )*
'"' !
;
